<?php

/**
 * Created by PhpStorm.
 * User: gx1727
 * Date: 2016-05-28
 * Time: 14:12
 */
class XXImgThumbnail
{
    var $base_path; //根地址
    var $default; //默认图
    var $max_width;
    var $max_height;
    var $zoomed; //是否要缩略图　当原图的x y 都小于目标值时，是否需要放大处理　
    var $image_path;
    var $mod; // 0:原图 1:模式一　2:模式二 3:模式三
    var $cutting_position; //裁切位置　在模式三时使用　1: 左　或　高　2:中　3:右　或　下
    var $bgcolor; //背景色
    var $mime; //原图的mime信息

    var $dst_image; //新建的图片
    var $src_image; //需要载入的图片
    var $dst_x; //设定需要载入的图片在新图中的x坐标
    var $dst_y; //设定需要载入的图片在新图中的y坐标
    var $src_x; //设定载入图片要载入的区域x坐标
    var $src_y; //设定载入图片要载入的区域y坐标
    var $dst_w; //设定载入的原图的宽度（在此设置缩放）
    var $dst_h; //设定载入的原图的高度（在此设置缩放）
    var $src_w; //原图要载入的宽度
    var $src_h; //原图要载入的高度

    var $quality; //范围从 0（最差质量，文件更小）到 100（最佳质量，文件最大）
    var $dst_width; //最终出图宽
    var $dst_height; //最终出图高
    var $file_cache; //是否使用文件缓存，当此项为true里，应请求得出的小图创建一个文件缓存，以便下次直接使用，不用重新计算

    function __construct($image_path = false)
    {
        $this->base_path = '';
        $this->default = 'images/defaultpic.gif';
        $this->max_width = 200;
        $this->max_height = 200;
        $this->zoomed = false;
        $this->image_path = '';
        $this->mod = 1;
        $this->cutting_position = 2;
        $this->bgcolor = array(255, 255, 255); //默认为白色
        $this->mime = 'image/jpeg';

        $this->dst_image = false; //新建的图片
        $this->src_image = false; //需要载入的图片
        $this->dst_x = 0; //设定需要载入的图片在新图中的x坐标
        $this->dst_y = 0; //设定需要载入的图片在新图中的y坐标
        $this->src_x = 0; //设定载入图片要载入的区域x坐标
        $this->src_y = 0; //设定载入图片要载入的区域y坐标
        $this->dst_w = 0; //设定载入的原图的宽度（在此设置缩放）
        $this->dst_h = 0; //设定载入的原图的高度（在此设置缩放）
        $this->src_w = 0; //原图要载入的宽度
        $this->src_h = 0; //原图要载入的高度

        $this->quality = 80;
        $this->file_cache = true; //默认开启

        if ($image_path) {
            $this->init($image_path);
        }

        $this->dst_width = $this->max_width; //最终出图宽
        $this->dst_height = $this->max_height; //最终出图高
    }

    public function init($image_path)
    {
        if (file_exists($image_path)) {
            $this->image_path = $image_path;
        } else {
            $this->image_path = $this->default;
        }
        $size = getimagesize($this->image_path);   //得到图像的大小

        $this->src_w = $size[0];//原图要载入的宽度
        $this->src_h = $size[1];//原图要载入的高度
        $this->mime = $size['mime'];

        if ($this->src_image) {
            imagedestroy($this->src_image);
        }
        $this->src_image = $this->get_image_src($this->mime, $this->image_path);
    }

    /**
     * 显示图片
     */
    public function show()
    {
        if ($this->file_cache) {
            $file_path_arr = explode('.', $this->image_path);
            $file_suffix = array_pop($file_path_arr);

            //缓存文件名
            $cache_file_path = implode('.', $file_path_arr) . '_' . $this->max_width . '_' . $this->max_height . '_' . $this->mod . ".jpg";
            if (!file_exists($cache_file_path)) {
                $this->save($cache_file_path);
            }
            $fp = fopen($cache_file_path, 'rb');
            header('Content-Type: image/jpeg');
            header("Content-Length: " . filesize($cache_file_path));
            fpassthru($fp);
            $fp->close();
            exit;
        } else {
            $this->manage();

            $this->dst_image = imagecreatetruecolor($this->dst_width, $this->dst_height); //新建一个真彩色图像

            // 设置背景色
            $bgcolor = imagecolorallocate($this->dst_image, $this->bgcolor[0], $this->bgcolor[1], $this->bgcolor[2]);
            imagefill($this->dst_image, 0, 0, $bgcolor);

            imagecopyresampled($this->dst_image, $this->src_image, $this->dst_x, $this->dst_y, $this->src_x, $this->src_y, $this->dst_w, $this->dst_h, $this->src_w, $this->src_h);        //重采样拷贝部分图像并调整大小
            header('Content-Type: image/jpeg');
            imagejpeg($this->dst_image, null, $this->quality);

            $this->destroy();
        }
    }


    /**
     * 保存图片
     * @param $save_path
     */
    public function save($save_path)
    {
        $this->manage();

        $this->dst_image = imagecreatetruecolor($this->dst_width, $this->dst_height); //新建一个真彩色图像

        // 设置背景色
        $bgcolor = imagecolorallocate($this->dst_image, $this->bgcolor[0], $this->bgcolor[1], $this->bgcolor[2]);
        imagefill($this->dst_image, 0, 0, $bgcolor);

        imagecopyresampled($this->dst_image, $this->src_image, $this->dst_x, $this->dst_y, $this->src_x, $this->src_y, $this->dst_w, $this->dst_h, $this->src_w, $this->src_h);        //重采样拷贝部分图像并调整大小
        imagejpeg($this->dst_image, $save_path, $this->quality);
        $this->destroy();
    }

    public function destroy()
    {
        if ($this->src_image) {
            imagedestroy($this->src_image);
        }
        if ($this->dst_image) {
            imagedestroy($this->dst_image);
        }
    }

    /**
     * 设置目录图片尽寸
     * @param $width
     * @param $height
     */
    public function set_max_size($width, $height)
    {
        $this->max_width = $width;
        $this->max_height = $height;
    }

    /**
     * @param $mod 0:原图 1:模式一　2:模式二 3:模式三
     */
    public function set_mod($mod)
    {

        if ($mod > 10) {
            $this->cutting_position = $mod % 10;
            $mod = floor($mod / 10);
        }
        //
        $this->mod = $mod;
    }

    /**
     * 设置背景色
     * @param $red  红 0-255
     * @param $green  绿 0-255
     * @param $blue  蓝 0-255
     */
    public function set_bkcolor($red, $green, $blue)
    {
        $this->bgcolor = array($red, $green, $blue); //默认为白色
    }

    /**
     * 图片质量
     * @param $quality 0-100
     */
    public function set_quality($quality)
    {
        $this->quality = $quality;
    }

    /**
     * 设置默认图片地址
     * @param $default
     */
    public function set_default($default)
    {
        $this->default = $default;
    }

    /**
     * 根据mime信息，获取图片的源信息
     * @param $mime
     * @param $image_path
     * @return resource
     */
    private function get_image_src($mime, $image_path)
    {
        if ($mime == "image/jpeg") {
            return imagecreatefromjpeg($image_path);
        } else if ($mime == "image/png") {
            return imagecreatefrompng($image_path);
        } else if ($mime == "image/gif") {
            return imagecreatefromgif($image_path);
        }
    }

    /**
     * 根据mod处理各个尺寸　坐标
     */
    private function manage()
    {
        if ($this->mod == 0) {
            //出图大小
            $this->dst_width = $this->src_w;
            $this->dst_height = $this->src_h;

            $this->dst_w = $this->src_w;
            $this->dst_h = $this->src_h;
        } else if ($this->mod == 1) {
            $x_ratio = $this->max_width / $this->src_w;
            $y_ratio = $this->max_height / $this->src_h;

            if (($this->src_w <= $this->max_width) && ($this->src_h <= $this->max_height)) {
                $this->dst_w = $this->src_w;
                $this->dst_h = $this->src_h;
            } elseif (($x_ratio * $this->src_h) < $this->max_height) { //以宽度为准
                $this->dst_w = $this->max_width;
                $this->dst_h = ceil($x_ratio * $this->src_h);
            } else {
                $this->dst_w = ceil($y_ratio * $this->src_w);
                $this->dst_h = $this->max_height;
            }

            $this->dst_width = $this->dst_w;
            $this->dst_height = $this->dst_h;
        } else if ($this->mod == 2) {
            $x_ratio = $this->max_width / $this->src_w;
            $y_ratio = $this->max_height / $this->src_h;

            if (($this->src_w <= $this->max_width) && ($this->src_h <= $this->max_height)) {
                $this->dst_w = $this->src_w;
                $this->dst_h = $this->src_h;
            } elseif (($x_ratio * $this->src_h) < $this->max_height) { //以宽度为准
                $this->dst_w = $this->max_width;
                $this->dst_h = ceil($x_ratio * $this->src_h);
            } else {
                $this->dst_w = ceil($y_ratio * $this->src_w);
                $this->dst_h = $this->max_height;
            }

            $this->dst_width = $this->max_width;
            $this->dst_height = $this->max_height;
            if ($this->dst_w < $this->dst_width) { //最终计算宽度没有出图宽度　大，图片右移至居中，左右两边留背景色
                $this->dst_x = ($this->dst_width - $this->dst_w) / 2;
            }
            if ($this->dst_h < $this->dst_height) {//最终计算高度没有出图高度　大，图片下移至居中，上下留背景色
                $this->dst_y = ($this->dst_height - $this->dst_h) / 2;
            }
        } else if ($this->mod == 3) { //模式三
            $x_ratio = $this->max_width / $this->src_w;
            $y_ratio = $this->max_height / $this->src_h;

            if (($this->src_w <= $this->max_width) && ($this->src_h <= $this->max_height)) {
                $this->dst_w = $this->src_w;
                $this->dst_h = $this->src_h;
            } elseif (($x_ratio * $this->src_h) > $this->max_height) { //以宽度为准
                $this->dst_w = $this->max_width;
                $this->dst_h = ceil($x_ratio * $this->src_h);
            } else {
                $this->dst_w = ceil($y_ratio * $this->src_w);
                $this->dst_h = $this->max_height;
            }

            $this->dst_width = $this->max_width;
            $this->dst_height = $this->max_height;
            if ($this->dst_w > $this->dst_width) { //最终计算宽度　大于　出图宽度，向右移裁切　左右有损失
                if ($this->cutting_position == 1) {
                    $this->dst_x = 0;
                } else if ($this->cutting_position == 2) {
                    $this->dst_x = ($this->dst_width - $this->dst_w) / 2;
                } else if ($this->cutting_position == 3) {
                    $this->dst_x = ($this->dst_width - $this->dst_w);
                }

            }
            if ($this->dst_h > $this->dst_height) {//最终计算高度　大于　出图高度，向下移裁切，上下有损失
                if ($this->cutting_position == 1) {
                    $this->dst_y = 0;
                } else if ($this->cutting_position == 2) {
                    $this->dst_y = ($this->dst_height - $this->dst_h) / 2;
                } else if ($this->cutting_position == 3) {
                    $this->dst_y = ($this->dst_height - $this->dst_h);
                }
            }
        }
    }
}